/***************************************************************************
                          Zoomable.hpp  -  description
                             -------------------
    begin                : October 29 2009
    copyright            : Copyright 2009, ACKERMANN Thibaut
    email                : tackerma@edu.univ-fcomte.fr
    website              : http://code.google.com/p/nover-project/
    license              : GNU GPL v3
 ***************************************************************************/
/* *************************************************************************
 *  This file is part of NOver-Project.
 *  
 *  NOver-Project is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *  
 *  NOver-Project is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *  
 *  You should have received a copy of the GNU General Public License
 *  along with NOver-Project.  If not, see <http://www.gnu.org/licenses/>.
 * *************************************************************************/


#ifndef _ZOOMABLE_
#define _ZOOMABLE_

#include <irrlicht.h>

#include <string>

#include "StateMgr.hpp"
#include <iostream>

using namespace irr;


/**
 *  Niveau de zoom :
 * 0 : Toute la texture est visible. 
 *  	(ne prend pas forcement toute la taille du AbsoluteRect)
 * 1 : Taille optimale. 
 * 		(le coté le plus large du AbsoluteRect est prit comme taille de reference pour la texture)
 * 2 : Zoom à 50%
 */
enum eZoomLevel
{
	ZOOM_LEVEL_0_ALL = 0,
	ZOOM_LEVEL_1_OPTIMAL,
	ZOOM_LEVEL_2_ZOOMED
};


/**
 * La classe Zoomable est un nouveau widget pour l'interface graphique
 * Elle gere l'affichage, le zoom et le 'drag and drop' d'une image.
 * @author Thibaut Ackermann
 */
class Zoomable : public gui::IGUIElement
{
public:
	
	Zoomable(IGUIElement* parent, s32 id, core::rect<s32> rectangle);
	
	~Zoomable();
	
	// fonction de dessin
	void draw();
	
	// defini la texture à utiliser.
	void setImage(video::ITexture* Texture)
	{
		this->Texture = Texture;
		
		if(Texture)
			calculateRendersRect();
	}
	
	// pour le resize de fenetre
	void setAbsolute(core::rect<int> abs)
	{
		AbsoluteRect = abs;
		calculateRendersRect();
	}
	
	core::rect<int> getAbsolute()
	{
		return AbsoluteRect;
	}
	
	core::rect<int> getAbsoluteRender()
	{
		return AbsoluteRenderRect;
	}
	
	void ScreenToTexture(int xscr, int yscr, int* xtex, int* ytex)
	{
		if(!AbsoluteRenderRect.isPointInside(position2d<int>(xscr, yscr)))
		{
			*xtex = -1;
			*ytex = -1;
			return;
		}
		
		int xMin = TextureRenderRect.UpperLeftCorner.X;
		int xMax = TextureRenderRect.LowerRightCorner.X;
		int yMin = TextureRenderRect.UpperLeftCorner.Y;
		int yMax = TextureRenderRect.LowerRightCorner.Y;
	
		*xtex = ((xscr*(xMax - xMin))/static_cast<float>(AbsoluteRenderRect.LowerRightCorner.X)) + xMin;
		*ytex = ((yscr*(yMax - yMin))/static_cast<float>(AbsoluteRenderRect.LowerRightCorner.Y)) + yMin;
		
	}
	
	void TextureToScreen(int xtex, int ytex, int* xscr, int* yscr)
	{
		core::rect<int> TextureRect = core::rect<int>(0, 0, Texture->getOriginalSize().Width, Texture->getOriginalSize().Height);
		if(!TextureRect.isPointInside(core::position2d<int>(xtex, ytex)))
		{
			*xscr = -1;
			*yscr = -1;
			return;
		}
		
		int xMin = TextureRenderRect.UpperLeftCorner.X;
		int xMax = TextureRenderRect.LowerRightCorner.X;
		int yMin = TextureRenderRect.UpperLeftCorner.Y;
		int yMax = TextureRenderRect.LowerRightCorner.Y;
	
		*xscr = ((xtex - xMin)*static_cast<float>(AbsoluteRenderRect.LowerRightCorner.X))/(xMax-xMin);
		*yscr = ((ytex - yMin)*static_cast<float>(AbsoluteRenderRect.LowerRightCorner.Y))/(yMax-yMin);
		
	}
	
	
	// zoomer
	void ZoomIn()
	{
		if(zoomlevel < ZOOM_LEVEL_2_ZOOMED)
			zoomlevel = static_cast<eZoomLevel>(zoomlevel + 1);
		
		calculateRendersRect();
		
		cout << "zoom:" << zoomlevel << endl;
	}
	
	// dézoomer
	void ZoomOut()
	{
		if(zoomlevel > ZOOM_LEVEL_0_ALL)
			zoomlevel = static_cast<eZoomLevel>(zoomlevel - 1);
		
		calculateRendersRect();
		
		cout << "zoom:" << zoomlevel << endl;
	}
	
	// déplace le point (x1,y1) vers le point (x2,y2) de la texture
	void Drag(int x1, int y1, int x2, int y2);
	
private:
	
	video::ITexture* Texture;
	
	eZoomLevel zoomlevel;
	
	core::rect<s32> AbsoluteRenderRect;
	
	core::rect<s32> TextureRenderRect;
	
	void calculateRendersRect();
};


#endif

